package com.hmdp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.hmdp.dto.Result;
import com.hmdp.dto.VoucherOrderDto;
import com.hmdp.entity.VoucherOrder;
import com.hmdp.mapper.VoucherOrderMapper;
import com.hmdp.service.ISeckillVoucherService;
import com.hmdp.service.IVoucherOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.utils.RabbitMqHelper;
import com.hmdp.utils.RedisIdWorker;
import com.hmdp.utils.UserHolder;
import lombok.RequiredArgsConstructor;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static com.hmdp.utils.RedisConstants.SECKILL_ORDER_KEY;
import static com.hmdp.utils.RedisConstants.SECKILL_STOCK_KEY;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Service
@RequiredArgsConstructor
public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {

    private final ISeckillVoucherService seckillVoucherService;
    private final RedisIdWorker redisIdWorker;
    private final StringRedisTemplate stringRedisTemplate;
    private final RabbitMqHelper rabbitMqHelper;
    private static final DefaultRedisScript<Long> seckillScript;
    //放在静态代码块里面，这样只需要执行一次，不会多次创建浪费io
    static {
        seckillScript=new DefaultRedisScript<>();
        seckillScript.setLocation(new ClassPathResource("seckill.lua"));
        seckillScript.setResultType(Long.class);
    }
    @Override
    @Transactional
    //用redis代替数据库
        public Result scellVoucher(Long voucherId) {
        //下面这段改写成lua脚本，确保原子性
        //从redis里面拿到库存
//        String voucherKey = SECKILL_STOCK_KEY+voucherId;
//        String value = stringRedisTemplate.opsForValue().get(voucherKey);
//        if(value==null) return Result.fail("不存在此商品");
//        int stock = Integer.parseInt(value);
//        if(stock<=0) return Result.fail("库存不足");
//        //判断用户是否已经下单
//        Boolean isOrder = stringRedisTemplate.opsForSet().isMember(voucherKey, String.valueOf(UserHolder.getUser().getId()));
//        if(Boolean.TRUE.equals(isOrder)) return Result.fail("无法重复下单");
//        //扣减库存，保存用户信息
//        stringRedisTemplate.opsForValue().set(voucherKey, String.valueOf((stock-1)));
//        stringRedisTemplate.opsForSet().add(voucherKey, String.valueOf(UserHolder.getUser().getId()));

        // 准备键和参数
        List<String> keys = Arrays.asList(SECKILL_STOCK_KEY + voucherId,SECKILL_ORDER_KEY+voucherId);
        List<String> args = Collections.singletonList(String.valueOf(UserHolder.getUser().getId()));

        // 执行Lua脚本
        Long result =stringRedisTemplate.execute(
            seckillScript,
            keys,
            args.toArray()
        );
        // 处理返回结果
        if (result == -1) {
            return Result.fail("不存在此商品");
        } else if (result == 0) {
            return Result.fail("库存不足");
        } else if (result == -2) {
            return Result.fail("无法重复下单");
        }
        //到这里就是可以下单了，将下单信息保存
        long orderId = redisIdWorker.nextId("order");
        Long userId = UserHolder.getUser().getId();
        VoucherOrderDto voucherOrderDto = new VoucherOrderDto(voucherId, userId, orderId);
        //异步发送消息到数据库添加订单信息
        rabbitMqHelper.sendMessage("order.direct", "order.success",voucherOrderDto);
        return Result.ok(orderId);

    }
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "order.queue", durable = "true"),
            exchange = @Exchange(name = "order.direct"),
            key = "order.success"
    ))
    public void saveVoucherOrder(VoucherOrderDto voucherOrderDto) {
        VoucherOrder voucherOrder = BeanUtil.copyProperties(voucherOrderDto, VoucherOrder.class);
        save(voucherOrder);
    }
//    public Result scellVoucher(Long voucherId) {
//        SeckillVoucher voucher = seckillVoucherService.getById(voucherId);
//        Integer stock = voucher.getStock();
//        if(stock<=0) return Result.fail("库存不足");
//        //尝试扣减库存
//        if(Objects.equals(seckillVoucherService.getById(voucherId).getStock(), stock)){
//            seckillVoucherService.update()
//                    .setSql("stock=stock-1")
//                    .eq("voucher_id",voucherId)
//                    .update();
//        }else scellVoucher(voucherId);
//        //创建订单
//        VoucherOrder voucherOrder = new VoucherOrder();
//        long id = redisIdWorker.nextId("order");
//        voucherOrder.setId(id);
//        voucherOrder.setUserId(UserHolder.getUser().getId());
//        voucherOrder.setVoucherId(voucherId);
//        save(voucherOrder);
//        return Result.ok(id);
//    }
}
